//
//  String+SJHandle.swift
//  SJSwiftKit
//
//  Created by swordjoy on 2017/2/16.
//  Copyright © 2017年 swordjoy. All rights reserved.
//

import Foundation

public extension SJStringProxy {
    
  // MARK: - property
  
  /// 字符串中字符数量
  public var length: Int { return base.characters.count }
  
  /// 字符串中字符数组
  public var array: [String] { return base.description.characters.map { String($0) } }
  
  /// 获取第一个字符
  public var first: String? {
    if array.count > 0 {
      return array[0]
    }
    return nil
  }
  
  /// 一般字母数字用
  public var ASCII: Int {
    if length != 1 { fatalError("(:") }
    return Int(UnicodeScalar(base)!.value)
  }
  
  /// 转换成可读的UUID,无<>, " ", "-"符号
  public var readableUUID: String {
    return base.trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "-", with: "")
  }
  
  /// 路径字符串获取文件名
  public var lastPathComponent: String {
    return NSString(string: base).lastPathComponent 
  }
  
  /// 路径或文件字符串获取文件扩展名
  public var pathExtension: String {
    return NSString(string: base).pathExtension 
  }
  
  /// 路径字符串删除文件名后的字符串
  public var deletingLastPathComponent: String {
    return NSString(string: base).deletingLastPathComponent
  }
  
  /// 路径字符串删除文件名扩展名后的字符串
  public var deletingPathExtension: String {
    return NSString(string: base).deletingPathExtension
  }
  
  /// 路径各个部分数组
  public var pathComponents: [String] {
    return NSString(string: base).pathComponents
  }
  
  
  /// 转换成Float
  public var floatValue: Float? { return Float(base) }
  
  /// 转换成Int
  public var intValue: Int? { return Int(base) }
  
  public var int64Value: Int64? { return Int64(base) }
  
  /// 转换成Double
  public var doubleValue: Double? { return Double(base) }
  
  /// 转换成data
  public var dataValue: Data? { return base.data(using: .utf8) }
  
  /// 转换成base64编码
  public var base64encoded: String? { return dataValue?.base64EncodedString() }
  
  /// base64解码
  public var base64decoded: String? {
    let data = Data(base64Encoded: base, options: .ignoreUnknownCharacters)
    guard let temp = data else { return nil }
    let dataString = String(data: temp, encoding: .utf8)
    return dataString
  }
  
  /// 百分号编码URL字符串
  public var urlEncoded: String? {
    return base.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)
  }
  
  // MARK: - function
  
  /// 获取字符串的长度
  ///
  /// - Returns: 字符串长度
  
  /// 截取字符串
  ///
  /// 这里采用的(],左开右闭区间
  ///
  ///  "0123".sj.cut(to: 1)     0
  ///  "0123".sj.cut(from: 1)   123
  ///  "0123".sj.cutString(location: 0, length: 4)    0123
  ///
  /// - Parameters:
  ///   - location: 开始截取位置,0开始
  ///   - length: 结束截取位置
  /// - Returns: 截取后的字符串
  public func cutString(location: Int, length: Int) -> String {
    if (base.isEmpty) {
        return ""
    }
    let len = self.length
    guard (location <= len) && (len - location >= length) else {
      fatalError("beyond endIndex")
    }
    
    let start = base.index(base.startIndex, offsetBy: location)
    let end = base.index(start, offsetBy: length)
    return base.substring(with: Range(start..<end))
  }
  
  /// 截取开始默认为0
  ///
  /// - Parameter to: 结束位置
  /// - Returns: 截取后的字符串
  public func cut(to: Int) -> String {
    return cutString(location: 0, length: to)
  }
  
  
  /// 截取结束默认为字符长
  ///
  /// - Parameter from: 截取开始位置
  /// - Returns: 截取后的字符串
  public func cut(from: Int) -> String {
    let length = self.length - from
    return cutString(location: from, length: length)
  }
  
  /// 路径字符串添加文件(URL代替了)
  ///
  /// - Parameter path: 文件名
  /// - Returns: 添加后的路径
  public func appendingPathComponent(_ path: String) -> String {
    let string = NSString(string: base)
    return string.appendingPathComponent(path)
  }
  
  /// 路径字符串添加扩展名
  ///
  /// - Parameter ext: 扩展名
  /// - Returns: 添加后的字符串
  public func appendingPathExtension(_ ext: String) -> String? {
    let nsSt = NSString(string: base)
    return nsSt.appendingPathExtension(ext)
  }
  
  
  /// 中文转换为拼音
  ///
  /// - Returns: 拼音
  public func chineseToPinYin() -> String {
    let mutableString = NSMutableString(string: base)
    
    if CFStringTransform(mutableString, nil, kCFStringTransformToLatin, false) {
      if CFStringTransform(mutableString, nil, kCFStringTransformStripDiacritics, false) {
        let string = String(mutableString)
        return string.replacingOccurrences(of: " ", with: "")
      }
    }

    return base
  }

}

extension SJStringProxy {
    func requireHeight3(width: CGFloat, font: UIFont) -> CGFloat {
        if base.isEmpty { return 0 }
        let textView = UITextView(frame: CGRect(x: 0, y: 0, width: width, height: 0))
        textView.font = font
        textView.text = base
        let layout = textView.layoutManager
        let container = textView.textContainer
        let focusRingFrame = layout.boundingRect(forGlyphRange: NSMakeRange(0, textView.textStorage.length), in: container)
        return focusRingFrame.height
    }
    
  func width(with font: UIFont) -> CGFloat {
    return UIFont.calculateWidth(font: font, text: base)
  }
    
    func requiredHeight1(width: CGFloat, font: UIFont) -> CGFloat {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = .byCharWrapping
        paragraphStyle.alignment = .left
        
        let attribute = [NSFontAttributeName : font,
                         NSParagraphStyleAttributeName : paragraphStyle]
        let tempRect = CGSize(width: width,
                              height: CGFloat.greatestFiniteMagnitude)
        let textSize = base.boundingRect(with: tempRect,
                                              options: [.usesLineFragmentOrigin, .usesFontLeading, .truncatesLastVisibleLine],
                                              attributes: attribute,
                                              context: nil)
        
        return textSize.height
    }
    
    func requireHeight2(width: CGFloat, font: UIFont) -> CGFloat {
        let attributes: [String: Any] = [NSFontAttributeName: font]
        let attributedString = NSAttributedString(string: base, attributes: attributes)
        let largestSize = CGSize(width: width, height: .greatestFiniteMagnitude)
        
        //Option one (best option)
        let framesetter = CTFramesetterCreateWithAttributedString(attributedString)
        let textSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRange(), nil, largestSize, nil)
        return textSize.height
    }
    
    /**
     根据字体和约束条件计算文字的Size
     
     - parameter constraintSize: 约束Size
     - parameter font:           字体大小
     
     - returns: 最终计算出来的size
     */
    func getStrSize(constraintSize: CGSize, font: UIFont) -> CGSize {
        let boundingBox = base.boundingRect(with: constraintSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
        
        return boundingBox.size
    }
    
    /**
     根据字体和宽度计算文字高度
     
     - parameter width: 约束宽度
     - parameter font:  字体大小
     
     - returns: 高度
     */
    func heightWithConstrainedWidth(width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        
        let boundingBox = base.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
        
        return boundingBox.height
    }
    
    /**
     根据字体和宽度计算文字宽度
     
     - parameter width: 约束宽度
     - parameter font:  字体大小
     
     - returns: 宽度
     */
    func widthWithConstrainedWidth(width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        
        let boundingBox = base.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
        
        return boundingBox.width
    }

}
